<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"><title>每日一面--SpringBoot启动原理 | Celts</title><meta name="author" content="PaulGeorge"><meta name="copyright" content="PaulGeorge"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="每天一篇面试小知识  本篇着重介绍一下 SpringBoot 启动原理：   写在前面 最近在不断的面试中总结Spring全家桶已经是必须要熟练掌握的框架了，其中化繁为简的SpringBoot更是经常被提及的框架，所以我今天就来聊聊 SpringBoot。 说起SpringBoot的江湖地位，由于其设计优雅，实现简单，可以节省不少开发时间。">
<meta property="og:type" content="article">
<meta property="og:title" content="每日一面--SpringBoot启动原理">
<meta property="og:url" content="https://curry3035.gitee.io/posts/65011/index.html">
<meta property="og:site_name" content="Celts">
<meta property="og:description" content="每天一篇面试小知识  本篇着重介绍一下 SpringBoot 启动原理：   写在前面 最近在不断的面试中总结Spring全家桶已经是必须要熟练掌握的框架了，其中化繁为简的SpringBoot更是经常被提及的框架，所以我今天就来聊聊 SpringBoot。 说起SpringBoot的江湖地位，由于其设计优雅，实现简单，可以节省不少开发时间。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://curry3035.gitee.io/img/avatar.jpg">
<meta property="article:published_time" content="2021-06-27T13:58:58.000Z">
<meta property="article:modified_time" content="2022-12-10T12:07:49.769Z">
<meta property="article:author" content="PaulGeorge">
<meta property="article:tag" content="进阶">
<meta property="article:tag" content="SpringBoot">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://curry3035.gitee.io/img/avatar.jpg"><link rel="shortcut icon" href="/img/ic.ico"><link rel="canonical" href="https://curry3035.gitee.io/posts/65011/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: {"path":"/search.xml","preload":false,"languages":{"hits_empty":"找不到您查询的内容：${query}"}},
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":false,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: true,
    post: true
  },
  runtime: '天',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: {"limitCount":50,"languages":{"author":"作者: PaulGeorge","link":"链接: ","source":"来源: Celts","info":"著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。"}},
  lightbox: 'fancybox',
  Snackbar: {"chs_to_cht":"你已切换为繁体","cht_to_chs":"你已切换为简体","day_to_night":"你已切换为深色模式","night_to_day":"你已切换为浅色模式","bgLight":"#49b1f5","bgDark":"#1f1f1f","position":"top-right"},
  source: {
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: false,
  isAnchor: false,
  percent: {
    toc: true,
    rightside: false,
  }
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: '每日一面--SpringBoot启动原理',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2022-12-10 20:07:49'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
    win.getCSS = (url,id = false) => new Promise((resolve, reject) => {
      const link = document.createElement('link')
      link.rel = 'stylesheet'
      link.href = url
      if (id) link.id = id
      link.onerror = reject
      link.onload = link.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        link.onload = link.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(link)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><link rel="stylesheet" href="/css/background.css"><link rel="stylesheet" href="/css/my.css"><meta name="generator" content="Hexo 5.4.2"></head><body><div id="web_bg"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="/img/avatar.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">97</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">64</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">25</div></a></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fa fa-archive"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fa fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fa fa-folder-open"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/photos/"><i class="fa-fw fa fa-camera-retro"></i><span> 图库</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://gcore.jsdelivr.net/gh/PaulGeorge123/cloudimg@img/mig2023/background05.jpg')"><nav id="nav"><span id="blog-info"><a href="/" title="Celts"><span class="site-name">Celts</span></a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search" href="javascript:void(0);"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fa fa-archive"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fa fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fa fa-folder-open"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/photos/"><i class="fa-fw fa fa-camera-retro"></i><span> 图库</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div><div id="toggle-menu"><a class="site-page" href="javascript:void(0);"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">每日一面--SpringBoot启动原理</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2021-06-27T13:58:58.000Z" title="发表于 2021-06-27 21:58:58">2021-06-27</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2022-12-10T12:07:49.769Z" title="更新于 2022-12-10 20:07:49">2022-12-10</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/%E9%9D%A2%E8%AF%95%E7%AF%87/">面试篇</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">2.8k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>10分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="每日一面--SpringBoot启动原理"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><blockquote>
<p>每天一篇面试小知识</p>
</blockquote>
<p><strong>本篇着重介绍一下 SpringBoot 启动原理：</strong></p>
<hr>
<p><img src="https://gcore.jsdelivr.net/gh/PaulGeorge123/cloudimg@master/img/all/Snipaste_2022-12-10_19-28-20.png"></p>
<p><strong>写在前面</strong></p>
<p>最近在不断的面试中总结<code>Spring</code>全家桶已经是必须要熟练掌握的框架了，其中化繁为简的<code>SpringBoot</code>更是经常被提及的框架，所以我今天就来聊聊 SpringBoot。</p>
<p>说起<code>SpringBoot</code>的江湖地位，由于其设计优雅，实现简单，可以节省不少开发时间。</p>
<span id="more"></span>



<blockquote>
<p>以下源码的 <code>SpringBoot</code> 版本：2.3.9.RELEASE</p>
</blockquote>
<p>其实<code>SpringBoot</code>的启动大体上分为 2 个步骤：</p>
<ol>
<li><p>启动类上注解：@SpringBootApplication</p>
</li>
<li><p>启动类中的main方法：org.springframework.boot.SpringApplication#run(java.lang.Class&lt;?&gt;, java.lang.String…)</p>
</li>
</ol>
<h3 id="启动原理"><a href="#启动原理" class="headerlink" title="启动原理"></a>启动原理</h3><h4 id="SpringBootApplication"><a href="#SpringBootApplication" class="headerlink" title="@SpringBootApplication"></a>@SpringBootApplication</h4><p>main 方法上的注解 @SpringBootApplication：</p>
<p>三个注解核心注解：</p>
<ul>
<li>@SpringBootConfiguration</li>
<li>@EnableAutoConfiguratio</li>
<li>@ComponentScan</li>
</ul>
<p><strong>@SpringBootConfiguration</strong></p>
<p>根据 Javadoc 可知，该注解作用就是将当前的类作为一个 <strong>JavaConfig</strong>，然后<strong>触发注解</strong><code>@EnableAutoConfiguration</code>和<code>@ComponentScan</code>的<strong>处理</strong>，本质上与**@Configuration**注解没有区别。</p>
<p><strong>@ComponentScan</strong></p>
<p>扫描的 <code>Spring</code> 对应的组件，如 <strong>@Componet</strong>，**@Repository**。</p>
<p><img src="https://gcore.jsdelivr.net/gh/PaulGeorge123/cloudimg@master/img/all/2465789-20210816175530643-158529875.png"></p>
<hr>
<p><strong>总结</strong></p>
<p><code>SpringBoot</code>工程运行后初始化<code>Spring</code>容器，扫描引导类所在的包加载<code>bean</code></p>
<h3 id="Spring注解"><a href="#Spring注解" class="headerlink" title="Spring注解"></a>Spring注解</h3><h4 id="注解的优势："><a href="#注解的优势：" class="headerlink" title="注解的优势："></a>注解的优势：</h4><ol>
<li>采用纯<code>java</code>代码，不在需要配置繁杂的<code>xml</code>文件。</li>
<li>在配置中也可享受面向对象带来的好处。</li>
<li>类型安全对重构可以提供良好的支持。</li>
<li>减少复杂配置文件的同时亦能享受到<code>springIoC</code>容器提供的功能。</li>
</ol>
<h3 id="配置文件的注解"><a href="#配置文件的注解" class="headerlink" title="配置文件的注解"></a>配置文件的注解</h3><h4 id="SpringBootApplication（自动配置）"><a href="#SpringBootApplication（自动配置）" class="headerlink" title="@SpringBootApplication（自动配置）"></a>@SpringBootApplication（自动配置）</h4><p>引导类上面的**@SpringBootApplication<strong>相当于是将：</strong>@Configuration** 、**@EnableAutoConfiguration** 、 <strong>@ComponentScan</strong> 三个注解的组合注解。</p>
<h3 id="EnableAutoConfiguration"><a href="#EnableAutoConfiguration" class="headerlink" title="@EnableAutoConfiguration"></a>@EnableAutoConfiguration</h3><p>也是组合注解，其中最关键的要是**@Import(AutoConfigurationImportSelector.class)**。</p>
<p>借助<strong>AutoConfigurationImportSelector</strong>，**@EnableAutoConfiguration<strong>可以帮助</strong>SpringBoot<strong>应用将所有符合条件的</strong>@Configuration<strong>配置都加载到当前</strong>SpringBoot<strong>创建并使用的</strong>IoC**容器。</p>
<p>项目启动时会去<strong>classpath</strong>中搜索所有<strong>META-INF/spring.factories</strong>配置文件，根据以**@ConditionalOnxxx**为前缀的注解来判断是否加载当前的配置类。</p>
<h4 id="ComponentScan"><a href="#ComponentScan" class="headerlink" title="@ComponentScan"></a>@ComponentScan</h4><p><strong>@ComponentScan</strong>注解主要是从约定的扫描路径中，识别标注了组件注册注解的类，并且把这些类自动注册到spring 。</p>
<ol>
<li>包路径：</li>
</ol>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@ComponentScan(&#123;&quot;com.xxx&quot;&#125;)</span></span><br></pre></td></tr></table></figure>

<ol start="2">
<li>类路径：</li>
</ol>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@ComponentScan(basePackageClasses=&#123;XxxService.class&#125;)</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>扫描路径可以配置，默认是从引导类所在的包开始及其子包下的所有文件</p>
</blockquote>
<h4 id="Configuration"><a href="#Configuration" class="headerlink" title="@Configuration"></a><strong>@Configuration</strong></h4><p>本身就是一个组件，用于定义配置类，可替换<strong>xml</strong>配置文件。被注解的类内部包含有一个或多个被**@Bean**注解的方法。</p>
<blockquote>
<p>作用于类上</p>
</blockquote>
<h4 id="Bean"><a href="#Bean" class="headerlink" title="@Bean"></a>@Bean</h4><p>将方法的返回值添加到容器中，<strong>AnnotationConfigWebApplicationContext</strong>类进行扫描，并用于构建<strong>bean</strong>定义，初始化<strong>Spring</strong>容器。</p>
<blockquote>
<p>作用于方法上</p>
</blockquote>
<h4 id="ConfigurationProperties"><a href="#ConfigurationProperties" class="headerlink" title="@ConfigurationProperties"></a>@ConfigurationProperties</h4><p>使用注解的方式将自定义的<strong>properties、yml</strong>文件映射到实体bean中。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="meta">@ConfigurationProperties(prefix = &quot;mail&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConfigProperties</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String hostName;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> port;</span><br><span class="line">    <span class="keyword">private</span> String from;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight properties"><table><tr><td class="code"><pre><span class="line"><span class="comment">#Simple properties</span></span><br><span class="line"><span class="attr">mail.hostname</span>=<span class="string">host@mail.com</span></span><br><span class="line"><span class="attr">mail.port</span>=<span class="string">1000</span></span><br><span class="line"><span class="attr">mail.from</span>=<span class="string">mailer@mail.com</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>如果不想使用@Configuration， 那么需要在@EnableConfigurationProperties(ConfigProperties.class)注解中手动导入配置文件</p>
</blockquote>
<h3 id="关于Bean的注解"><a href="#关于Bean的注解" class="headerlink" title="关于Bean的注解"></a>关于Bean的注解</h3><h4 id="Component"><a href="#Component" class="headerlink" title="@Component"></a>@Component</h4><p>泛指组件，当组件不好归类的时候，我们可以使用这个注解进行标注，作用就相当于 XML配置。</p>
<p><strong>@Component</strong>注解及其衍生注解**@RestController<strong>、</strong>@Controller<strong>、</strong>@Service<strong>和</strong>@Repository**都是组件注册注解。</p>
<h4 id="Controller、-RestController"><a href="#Controller、-RestController" class="headerlink" title="@Controller、@RestController"></a>@Controller、@RestController</h4><p>在控制层使用，处理请求。</p>
<p><strong>@Controller</strong> 一般应用在有返回界面的应用场景下.</p>
<p><strong>@RestController</strong> 如果只是接口，那么就用 RestController 来注解，</p>
<blockquote>
<p> @RestController = @Controller + @ResponseBody</p>
</blockquote>
<h4 id="Service"><a href="#Service" class="headerlink" title="@Service"></a>@Service</h4><p> 在业务逻辑层使用，就是对一个或多个DAO进行的再次封装，封装成一个服务，所以这里也就不会是一个原子操作了，需要事物控制。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Service(&quot;userServiceOne&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserServiceImplOne</span> <span class="keyword">implements</span> <span class="title class_">UserService</span> &#123; </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Service(&quot;userServiceTwo&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserServiceImplTwo</span> <span class="keyword">implements</span> <span class="title class_">UserService</span> &#123; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="meta">@Qualifier(&quot;userServiceOne&quot;)</span> </span><br><span class="line"><span class="keyword">private</span> UserService userService;</span><br></pre></td></tr></table></figure>



<h4 id="Repository"><a href="#Repository" class="headerlink" title="@Repository"></a>@Repository</h4><p>在数据访问层使用，</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Repository(value=&quot;userDao&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserDaoImpl</span> <span class="keyword">extends</span> <span class="title class_">BaseDaoImpl</span>&lt;User&gt; &#123; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="Autowired"><a href="#Autowired" class="headerlink" title="@Autowired"></a>@Autowired</h4><p>基于Spring规范开发，在实现注入功能的时候是基于By type的方式去注入</p>
<blockquote>
<p>根据被注解的属性的class，在容器中查找相同class的bean</p>
</blockquote>
<h4 id="Resource"><a href="#Resource" class="headerlink" title="@Resource"></a>@Resource</h4><p>基于Java的规范开发，在实现注入功能的时候是基于By name的方式来注入</p>
<blockquote>
<p>根据被注解的属性的name，在Spring容器中查找相同名字的bean</p>
</blockquote>
<h4 id="Order"><a href="#Order" class="headerlink" title="@Order"></a>@Order</h4><p><strong>@Order</strong>注解不能指定 <strong>bean</strong> 的加载顺序，它适用于 <strong>AOP</strong> 的优先级，以及将多个 <strong>Bean</strong> 注入到集合时，这些 <strong>bean</strong> 在集合中的顺序。</p>
<h3 id="Spring-常用配置注解"><a href="#Spring-常用配置注解" class="headerlink" title="Spring 常用配置注解"></a>Spring 常用配置注解</h3><h4 id="Import"><a href="#Import" class="headerlink" title="@Import"></a>@Import</h4><p>通过导入的方式实现把实例加入<strong>Spring IOC</strong>容器中。可以在需要时将没有被<strong>Spring</strong>容器管理的类导入至Spring容器中。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Import(&#123;User.class&#125;)</span></span><br></pre></td></tr></table></figure>



<h4 id="ImportResource"><a href="#ImportResource" class="headerlink" title="@ImportResource"></a>@ImportResource</h4><p>与**@Import<strong>类似，区别就是</strong>@ImportResource**导入的是配置文件。比如原项目已经将配置文件打成包，需要在原来的基础上进行新添加配置的时候导入原配置。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@ImportResource(&quot;classpath:spring-xxx.xml&quot;)</span>      <span class="comment">//导入xml配置</span></span><br></pre></td></tr></table></figure>



<h4 id="Scope"><a href="#Scope" class="headerlink" title="@Scope"></a>@Scope</h4><p><strong>Spring</strong>中<strong>bean</strong>的<strong>scope</strong>属性，有如下5种类型，在多数情况，我们只会使用<strong>singleton</strong>和<strong>prototype</strong>两种<strong>scope</strong>。</p>
<p>默认为单例</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Scope(&quot;singleton&quot;)</span></span><br></pre></td></tr></table></figure>

<p>更改为多例模式</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Scope(&quot;prototype&quot;)</span></span><br></pre></td></tr></table></figure>



<h4 id="Value"><a href="#Value" class="headerlink" title="@Value"></a>@Value</h4><p>作用是通过注解将常量、配置文件中的值和其他bean的属性值注入到变量中，作为变量的初始值。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Value(&quot;$&#123;user.age&#125;&quot;)</span></span><br><span class="line"><span class="keyword">private</span> String age;</span><br></pre></td></tr></table></figure>



<p>但是**@value**不能直接注入值给静态变量</p>
<p>解决方法：</p>
<ol>
<li>把@Value(value=”${xxx}”)放到静态变量的set方法上</li>
</ol>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**文件存储目录*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> String SAVE_PATH;</span><br><span class="line"></span><br><span class="line"><span class="comment">//记得去掉static</span></span><br><span class="line"><span class="meta">@Value(&quot;$&#123;local.file.temp.dir&#125;&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">setSavePath</span><span class="params">(String savePath)</span>&#123;</span><br><span class="line">    SAVE_PATH = savePath;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>配置文件：</p>
<figure class="highlight yml"><table><tr><td class="code"><pre><span class="line"><span class="attr">local:</span></span><br><span class="line">  <span class="attr">file:</span></span><br><span class="line">    <span class="attr">temp:</span></span><br><span class="line">      <span class="attr">dir :</span> <span class="string">/data/temp</span></span><br></pre></td></tr></table></figure>

<ol start="2">
<li>使用 <strong>@postconstruct</strong>，是在 <strong>bean</strong> 初始化过程中调用的，是在**@value**之后调用的，可以通过这种方式给静态变量赋值。</li>
</ol>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**文件存储目录*/</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> String SAVE_PATH;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Value(&quot;$&#123;local.file.temp.dir&#125;&quot;)</span></span><br><span class="line"><span class="keyword">public</span> String SAVE_PATH_TEMP;</span><br><span class="line"></span><br><span class="line"><span class="meta">@PostConstruct</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">init</span><span class="params">()</span>&#123;</span><br><span class="line">    SAVE_PATH = SAVE_PATH_TEMP;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@GetMapping(&quot;test&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test</span><span class="params">()</span>&#123;</span><br><span class="line">    System.out.println(SAVE_PATH);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<blockquote>
<p>@Value (“hello”)  –&gt; 普通字符串注入</p>
</blockquote>
<h4 id="PostConstruct"><a href="#PostConstruct" class="headerlink" title="@PostConstruct"></a>@PostConstruct</h4><p> 在构造函数执行完之后执行</p>
<h4 id="EnableScheduling"><a href="#EnableScheduling" class="headerlink" title="@EnableScheduling"></a>@EnableScheduling</h4><p>开启对计划任务的支持(定时器)</p>
<h4 id="Scheduled"><a href="#Scheduled" class="headerlink" title="@Scheduled"></a>@Scheduled</h4><p>声明这是一个计划任务 支持多种计划任务</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Scheduled(dixedDelay = 5000)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">prt</span><span class="params">()</span>&#123;</span><br><span class="line">    System.out.println(<span class="string">&quot;定时器...&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>







<h3 id="Enable-注解"><a href="#Enable-注解" class="headerlink" title="@Enable*注解"></a>@Enable*注解</h3><p><code>EnableXXX</code>这样的注解，通过这些注解我们可以很方便地启用某些功能，比如<code>@EnableAutoConfiguration</code>用来开启自动装配的功能。内部实现主要是通过<code>@Import</code>注解将指定的类实例注入之<code>Spring IOC Container</code>中，从下面代码可以看到<code>@EnableAutoConfiguration</code>的<code>@Import</code></p>
<h4 id="EnableAsync"><a href="#EnableAsync" class="headerlink" title="@EnableAsync"></a>@EnableAsync</h4><p> 开启异步任务的支持(多线程)</p>
<h4 id="EnableScheduling-1"><a href="#EnableScheduling-1" class="headerlink" title="@EnableScheduling"></a>@EnableScheduling</h4><p> 开启对计划任务的支持(定时器)</p>
<h4 id="EnableWebMVC"><a href="#EnableWebMVC" class="headerlink" title="@EnableWebMVC"></a>@EnableWebMVC</h4><p> 开启对Web MVC 的配置支持</p>
<h4 id="EnableAaspectJAutoProxy"><a href="#EnableAaspectJAutoProxy" class="headerlink" title="@EnableAaspectJAutoProxy"></a>@EnableAaspectJAutoProxy</h4><p>开启Spring 对 这个切面(Aspect )的支持</p>
<h4 id="EnableConfigurationProperties"><a href="#EnableConfigurationProperties" class="headerlink" title="@EnableConfigurationProperties"></a>@EnableConfigurationProperties</h4><p>开启对@ConfigurationProperties注解配置Bean的支持</p>
<h4 id="EnableJpaRepositories"><a href="#EnableJpaRepositories" class="headerlink" title="@EnableJpaRepositories"></a>@EnableJpaRepositories</h4><p>开启对Spring Data JAP Repository 的支持</p>
<h4 id="EnableTransactionManagement"><a href="#EnableTransactionManagement" class="headerlink" title="@EnableTransactionManagement"></a>@EnableTransactionManagement</h4><p>开启对注解式事物的支持</p>
<h4 id="EnableScheduling-2"><a href="#EnableScheduling-2" class="headerlink" title="@EnableScheduling"></a>@EnableScheduling</h4><p>让spring可以进行任务调度,功能类似于spring.xml文件中的命名空间</p>
<h4 id="EnableCaching"><a href="#EnableCaching" class="headerlink" title="@EnableCaching"></a>@EnableCaching</h4><p>开启Cache缓存支持;</p>
<h3 id="SpringMVC-常用注解"><a href="#SpringMVC-常用注解" class="headerlink" title="SpringMVC 常用注解"></a>SpringMVC 常用注解</h3><h4 id="RequestMapping"><a href="#RequestMapping" class="headerlink" title="@RequestMapping"></a>@RequestMapping</h4><ol>
<li><strong>value</strong>：指定 URL 请求的实际地址，是 @RequestMapping 的默认值。</li>
</ol>
<p>用于将特定 HTTP 请求方法映射到将处理相应请求的控制器中的特定类、方法。此注释可应用于两个级别：</p>
<ul>
<li>类级别：映射请求的 URL。</li>
<li>方法级别：映射 URL 以及 HTTP 请求方法。</li>
</ul>
<ol start="2">
<li><strong>method</strong>:指定请求的 method 类型，GET、POST、PUT、DELET。</li>
</ol>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(value = &quot;/index&quot;,method = RequestMethod.GET)</span></span><br></pre></td></tr></table></figure>

<p><strong>@RequestMapping</strong> 可进行 GET、POST、PUT、DELETE 等请求方法；</p>
<ul>
<li><strong>@GetMapping</strong>、**@PostMapping<strong>、</strong>@PutMapping<strong>、</strong>@DeleteMapping**</li>
</ul>
<ol start="3">
<li><strong>params</strong>：指定请求中必须包含某些参数，否则无法调用该方法。</li>
</ol>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(value = &quot;/index&quot;,method = RequestMethod.GET,params =&#123;&quot;name&quot;,&quot;id=10&quot;&#125;)</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">index</span><span class="params">()</span>&#123;</span><br><span class="line"> System.out.println(<span class="string">&quot;执行了index...&quot;</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="string">&quot;index&quot;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="RequestParam"><a href="#RequestParam" class="headerlink" title="@RequestParam"></a>@RequestParam</h4><p>@RequestParam有三个参数：</p>
<ol>
<li><p>value：参数名；</p>
</li>
<li><p>required：是否必需，默认为true，表示请求参数中必须包含该参数，如果不包含抛出异常。</p>
</li>
<li><p>defaultValue：默认参数值，如果设置了该值自动将required设置为false，如果参数中没有包含该参数则使用默认值。</p>
</li>
</ol>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@RequestParam(value = &quot;userId&quot;, required = false, defaultValue = &quot;1&quot;)</span></span><br></pre></td></tr></table></figure>



<h4 id="PathVariable"><a href="#PathVariable" class="headerlink" title="@PathVariable"></a>@PathVariable</h4><p>url 占位符映射时，url中可以通过一个或多个{xxxx}占位符映射，通过@PathVariable可以绑定占位符参数到方法参数中。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@RequestMapping(“/user/&#123;userId&#125;/&#123;userName&#125;/query&quot;)</span></span><br><span class="line"><span class="keyword">public</span> String <span class="title function_">index</span><span class="params">(<span class="meta">@PathVariable(&quot;userId&quot;)</span> Long userId,</span></span><br><span class="line"><span class="params">                    <span class="meta">@PathVariable(&quot;userName&quot;)</span> String userName)</span>&#123;</span><br><span class="line">	...</span><br><span class="line">   <span class="keyword">return</span> <span class="string">&quot;index&quot;</span>; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="RequestHeader"><a href="#RequestHeader" class="headerlink" title="@RequestHeader"></a>@RequestHeader</h4><p>通过此注解可以获取请求头相关信息。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line">Host                    localhost:<span class="number">8080</span></span><br><span class="line">Accept                  text/html,application/xhtml+xml,application/xml;q=<span class="number">0.9</span></span><br><span class="line">Accept-Language         fr,en-gb;q=<span class="number">0.7</span>,en;q=<span class="number">0.3</span></span><br><span class="line">Accept-Encoding         gzip,deflate</span><br><span class="line">Accept-Charset          ISO-<span class="number">8859</span>-<span class="number">1</span>,utf-<span class="number">8</span>;q=<span class="number">0.7</span>,*;q=<span class="number">0.7</span></span><br><span class="line">Keep-Alive              <span class="number">300</span></span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@GetMapping(&quot;/demo&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handle</span><span class="params">(</span></span><br><span class="line"><span class="params">        <span class="meta">@RequestHeader(&quot;Accept-Encoding&quot;)</span> String encoding,</span></span><br><span class="line"><span class="params">        <span class="meta">@RequestHeader(&quot;Keep-Alive&quot;)</span> <span class="type">long</span> keepAlive)</span> &#123;</span><br><span class="line">    <span class="comment">//...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="CookieValue"><a href="#CookieValue" class="headerlink" title="@CookieValue"></a>@CookieValue</h4><p>获取cookie</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@GetMapping(&quot;/demo&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handle</span><span class="params">(<span class="meta">@CookieValue(&quot;tok&quot;)</span> String cookie)</span> &#123;</span><br><span class="line">    <span class="comment">//...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="RequestBody"><a href="#RequestBody" class="headerlink" title="@RequestBody"></a>@RequestBody</h4><p>@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的)。</p>
<p>一个请求，只有一个RequestBody；一个请求，可以有多个RequestParam。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@GetMapping(&quot;/user&quot;)</span></span><br><span class="line"><span class="keyword">public</span> R <span class="title function_">queryUser</span><span class="params">(<span class="meta">@RequestBody</span> User user)</span> &#123;</span><br><span class="line">    <span class="comment">//...</span></span><br><span class="line">    <span class="keyword">return</span> R.success();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>







<h3 id="测试单元的注解"><a href="#测试单元的注解" class="headerlink" title="测试单元的注解"></a>测试单元的注解</h3><h4 id="SpringBootTest"><a href="#SpringBootTest" class="headerlink" title="@SpringBootTest"></a>@SpringBootTest</h4><p>获取启动类，加载配置，寻找主配置启动类（被 @SpringBootApplication 注解的）</p>
<h4 id="RunWith"><a href="#RunWith" class="headerlink" title="@RunWith"></a>@RunWith</h4><p>@RunWith(SpringRunner.class)，让JUnit运行Spring的测试环境,获得Spring环境的上下文的支持</p>
<h4 id="Test注解"><a href="#Test注解" class="headerlink" title="@Test注解"></a>@Test注解</h4><p>添加在测试方法上，表明这是一个测试方法。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@SpringBootTest</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Boot05WebAdminApplicationTests</span> &#123;</span><br><span class="line"> </span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">contextLoads</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="DisplayName"><a href="#DisplayName" class="headerlink" title="@DisplayName"></a>@DisplayName</h4><p>为测试类或者测试方法设置展示名称。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@DisplayName(&quot;junit5功能测试&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Junit5Test</span> &#123;</span><br><span class="line"> </span><br><span class="line">    <span class="meta">@DisplayName(&quot;测试displayname注解&quot;)</span></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">testDisplayName</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;测试displayname注解&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>





<h4 id="BeforeEach、-AfterEach、-BeforeAll、-AfterAll"><a href="#BeforeEach、-AfterEach、-BeforeAll、-AfterAll" class="headerlink" title="@BeforeEach、@AfterEach、@BeforeAll、@AfterAll"></a>@BeforeEach、@AfterEach、@BeforeAll、@AfterAll</h4><table>
<thead>
<tr>
<th align="center">注解</th>
<th align="center">作用</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>@BeforeEach</strong></td>
<td align="center">表示在<strong>每个</strong>单元测试<strong>之前</strong>执行</td>
</tr>
<tr>
<td align="center"><strong>@AfterEach</strong></td>
<td align="center">表示在<strong>每个</strong>单元测试<strong>之后</strong>执行</td>
</tr>
<tr>
<td align="center"><strong>@BeforeAll</strong></td>
<td align="center">表示在<strong>所有</strong>单元测试<strong>之前</strong>执行</td>
</tr>
<tr>
<td align="center"><strong>@AfterAll</strong></td>
<td align="center">表示在<strong>所有</strong>单元测试<strong>之后</strong>执行</td>
</tr>
</tbody></table>
<h4 id="Disabled"><a href="#Disabled" class="headerlink" title="@Disabled"></a>@Disabled</h4><p>表示测试类或测试方法不执行。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Disabled</span></span><br><span class="line"><span class="meta">@DisplayName(&quot;测试2&quot;)</span></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">test2</span><span class="params">()</span> &#123;</span><br><span class="line">    System.out.println(<span class="string">&quot;此测试方法不执行&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="Timeout"><a href="#Timeout" class="headerlink" title="@Timeout"></a>@Timeout</h4><p>表示测试方法运行如果超过了指定时间将会返回错误。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="meta">@Timeout(value = 500, unit = TimeUnit.MILLISECONDS)</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">testTimeOut</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">    Thread.sleep(<span class="number">520</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h4 id="RepeatedTest"><a href="#RepeatedTest" class="headerlink" title="@RepeatedTest"></a>@RepeatedTest</h4><p>表示方法可重复执行。</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@RepeatedTest(5)</span>    <span class="comment">//重复测试5次</span></span><br><span class="line"><span class="meta">@DisplayName(&quot;测试3&quot;)</span></span><br><span class="line"><span class="meta">@Test</span></span><br><span class="line"><span class="keyword">void</span> <span class="title function_">test3</span><span class="params">()</span> &#123;</span><br><span class="line">    System.out.println(<span class="string">&quot;重复测试&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>







<h3 id="事务注解"><a href="#事务注解" class="headerlink" title="事务注解"></a>事务注解</h3><h4 id="Transactional"><a href="#Transactional" class="headerlink" title="@Transactional"></a>@Transactional</h4><p><strong>声明式事务管理：</strong> 建立在AOP之上的。其本质是对方法前后进行拦截，然后在目标方法开始之前创建或者加入一个事务，在执行完目标方法之后根据执行情况提交或者回滚事务。</p>
<p>SpringBoot项目会自动配置一个 DataSourceTransactionManager，所以我们只需在方法（或者类）加上 @Transactional 注解，就自动纳入 Spring 的事务管理了</p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="meta">@Transactional</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">insertUser</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">User</span>(<span class="string">&quot;abc&quot;</span>);</span><br><span class="line">    userMapper.insertOneUser(user);          <span class="comment">//向数据库插入一条记录</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">RuntimeException</span>(<span class="string">&quot;发生异常&quot;</span>);   <span class="comment">//手动模拟抛出异常</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>抛出异常之后，事务会自动回滚，数据不会插入到数据库。</p>
</blockquote>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="https://curry3035.gitee.io">PaulGeorge</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://curry3035.gitee.io/posts/65011/">https://curry3035.gitee.io/posts/65011/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://curry3035.gitee.io" target="_blank">Celts</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/%E8%BF%9B%E9%98%B6/">进阶</a><a class="post-meta__tags" href="/tags/SpringBoot/">SpringBoot</a></div><div class="post_share"><div class="social-share" data-image="/img/avatar.jpg" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/posts/33770/" title="日积月累"><div class="cover" style="background: var(--default-bg-color)"></div><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">日积月累</div></div></a></div><div class="next-post pull-right"><a href="/posts/16824/" title="每日一面--Spring入门"><div class="cover" style="background: var(--default-bg-color)"></div><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">每日一面--Spring入门</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list"><div><a href="/posts/39089/" title="实践一下--SpringBoot多模块项目"><div class="cover" style="background: var(--default-bg-color)"></div><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-09-20</div><div class="title">实践一下--SpringBoot多模块项目</div></div></a></div><div><a href="/posts/55119/" title="每日一面--Files工具类"><div class="cover" style="background: var(--default-bg-color)"></div><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2023-01-01</div><div class="title">每日一面--Files工具类</div></div></a></div><div><a href="/posts/34600/" title="面试一下--JUC入门"><div class="cover" style="background: var(--default-bg-color)"></div><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-09-10</div><div class="title">面试一下--JUC入门</div></div></a></div><div><a href="/posts/11315/" title="实践一下--Spring Security"><div class="cover" style="background: var(--default-bg-color)"></div><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-06-01</div><div class="title">实践一下--Spring Security</div></div></a></div><div><a href="/posts/40042/" title="每日一面--反射"><div class="cover" style="background: var(--default-bg-color)"></div><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-05-01</div><div class="title">每日一面--反射</div></div></a></div><div><a href="/posts/56511/" title="实践一下--MySQL 优化"><div class="cover" style="background: var(--default-bg-color)"></div><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-01-04</div><div class="title">实践一下--MySQL 优化</div></div></a></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="/img/avatar.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">PaulGeorge</div><div class="author-info__description">很多事情就像是旅行一样，当你决定要出发的时候，最困难的那部分其实就已经完成了</div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">97</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">64</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">25</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/PaulGeorge123"><i class="fab fa-github"></i><span>GitHub URL</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/PaulGeorge123" target="_blank" title="Github"><i class="fab fa-github"></i></a></div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content is-expand"><ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%90%AF%E5%8A%A8%E5%8E%9F%E7%90%86"><span class="toc-number">1.</span> <span class="toc-text">启动原理</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#SpringBootApplication"><span class="toc-number">1.1.</span> <span class="toc-text">@SpringBootApplication</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Spring%E6%B3%A8%E8%A7%A3"><span class="toc-number">2.</span> <span class="toc-text">Spring注解</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%B3%A8%E8%A7%A3%E7%9A%84%E4%BC%98%E5%8A%BF%EF%BC%9A"><span class="toc-number">2.1.</span> <span class="toc-text">注解的优势：</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E6%B3%A8%E8%A7%A3"><span class="toc-number">3.</span> <span class="toc-text">配置文件的注解</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#SpringBootApplication%EF%BC%88%E8%87%AA%E5%8A%A8%E9%85%8D%E7%BD%AE%EF%BC%89"><span class="toc-number">3.1.</span> <span class="toc-text">@SpringBootApplication（自动配置）</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#EnableAutoConfiguration"><span class="toc-number">4.</span> <span class="toc-text">@EnableAutoConfiguration</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#ComponentScan"><span class="toc-number">4.1.</span> <span class="toc-text">@ComponentScan</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Configuration"><span class="toc-number">4.2.</span> <span class="toc-text">@Configuration</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Bean"><span class="toc-number">4.3.</span> <span class="toc-text">@Bean</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ConfigurationProperties"><span class="toc-number">4.4.</span> <span class="toc-text">@ConfigurationProperties</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%85%B3%E4%BA%8EBean%E7%9A%84%E6%B3%A8%E8%A7%A3"><span class="toc-number">5.</span> <span class="toc-text">关于Bean的注解</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Component"><span class="toc-number">5.1.</span> <span class="toc-text">@Component</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Controller%E3%80%81-RestController"><span class="toc-number">5.2.</span> <span class="toc-text">@Controller、@RestController</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Service"><span class="toc-number">5.3.</span> <span class="toc-text">@Service</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Repository"><span class="toc-number">5.4.</span> <span class="toc-text">@Repository</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Autowired"><span class="toc-number">5.5.</span> <span class="toc-text">@Autowired</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Resource"><span class="toc-number">5.6.</span> <span class="toc-text">@Resource</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Order"><span class="toc-number">5.7.</span> <span class="toc-text">@Order</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Spring-%E5%B8%B8%E7%94%A8%E9%85%8D%E7%BD%AE%E6%B3%A8%E8%A7%A3"><span class="toc-number">6.</span> <span class="toc-text">Spring 常用配置注解</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Import"><span class="toc-number">6.1.</span> <span class="toc-text">@Import</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ImportResource"><span class="toc-number">6.2.</span> <span class="toc-text">@ImportResource</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Scope"><span class="toc-number">6.3.</span> <span class="toc-text">@Scope</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Value"><span class="toc-number">6.4.</span> <span class="toc-text">@Value</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#PostConstruct"><span class="toc-number">6.5.</span> <span class="toc-text">@PostConstruct</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#EnableScheduling"><span class="toc-number">6.6.</span> <span class="toc-text">@EnableScheduling</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Scheduled"><span class="toc-number">6.7.</span> <span class="toc-text">@Scheduled</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Enable-%E6%B3%A8%E8%A7%A3"><span class="toc-number">7.</span> <span class="toc-text">@Enable*注解</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#EnableAsync"><span class="toc-number">7.1.</span> <span class="toc-text">@EnableAsync</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#EnableScheduling-1"><span class="toc-number">7.2.</span> <span class="toc-text">@EnableScheduling</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#EnableWebMVC"><span class="toc-number">7.3.</span> <span class="toc-text">@EnableWebMVC</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#EnableAaspectJAutoProxy"><span class="toc-number">7.4.</span> <span class="toc-text">@EnableAaspectJAutoProxy</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#EnableConfigurationProperties"><span class="toc-number">7.5.</span> <span class="toc-text">@EnableConfigurationProperties</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#EnableJpaRepositories"><span class="toc-number">7.6.</span> <span class="toc-text">@EnableJpaRepositories</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#EnableTransactionManagement"><span class="toc-number">7.7.</span> <span class="toc-text">@EnableTransactionManagement</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#EnableScheduling-2"><span class="toc-number">7.8.</span> <span class="toc-text">@EnableScheduling</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#EnableCaching"><span class="toc-number">7.9.</span> <span class="toc-text">@EnableCaching</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#SpringMVC-%E5%B8%B8%E7%94%A8%E6%B3%A8%E8%A7%A3"><span class="toc-number">8.</span> <span class="toc-text">SpringMVC 常用注解</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#RequestMapping"><span class="toc-number">8.1.</span> <span class="toc-text">@RequestMapping</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#RequestParam"><span class="toc-number">8.2.</span> <span class="toc-text">@RequestParam</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#PathVariable"><span class="toc-number">8.3.</span> <span class="toc-text">@PathVariable</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#RequestHeader"><span class="toc-number">8.4.</span> <span class="toc-text">@RequestHeader</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#CookieValue"><span class="toc-number">8.5.</span> <span class="toc-text">@CookieValue</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#RequestBody"><span class="toc-number">8.6.</span> <span class="toc-text">@RequestBody</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B5%8B%E8%AF%95%E5%8D%95%E5%85%83%E7%9A%84%E6%B3%A8%E8%A7%A3"><span class="toc-number">9.</span> <span class="toc-text">测试单元的注解</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#SpringBootTest"><span class="toc-number">9.1.</span> <span class="toc-text">@SpringBootTest</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#RunWith"><span class="toc-number">9.2.</span> <span class="toc-text">@RunWith</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Test%E6%B3%A8%E8%A7%A3"><span class="toc-number">9.3.</span> <span class="toc-text">@Test注解</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#DisplayName"><span class="toc-number">9.4.</span> <span class="toc-text">@DisplayName</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#BeforeEach%E3%80%81-AfterEach%E3%80%81-BeforeAll%E3%80%81-AfterAll"><span class="toc-number">9.5.</span> <span class="toc-text">@BeforeEach、@AfterEach、@BeforeAll、@AfterAll</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Disabled"><span class="toc-number">9.6.</span> <span class="toc-text">@Disabled</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Timeout"><span class="toc-number">9.7.</span> <span class="toc-text">@Timeout</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#RepeatedTest"><span class="toc-number">9.8.</span> <span class="toc-text">@RepeatedTest</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BA%8B%E5%8A%A1%E6%B3%A8%E8%A7%A3"><span class="toc-number">10.</span> <span class="toc-text">事务注解</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Transactional"><span class="toc-number">10.1.</span> <span class="toc-text">@Transactional</span></a></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/47231/" title="POI读取Excel问题">POI读取Excel问题</a><time datetime="2023-04-11T01:00:00.000Z" title="发表于 2023-04-11 09:00:00">2023-04-11</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/8422/" title="Excel大文件的上传">Excel大文件的上传</a><time datetime="2023-04-10T01:00:00.000Z" title="发表于 2023-04-10 09:00:00">2023-04-10</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/55119/" title="每日一面--Files工具类">每日一面--Files工具类</a><time datetime="2023-01-01T01:00:00.000Z" title="发表于 2023-01-01 09:00:00">2023-01-01</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/34600/" title="面试一下--JUC入门">面试一下--JUC入门</a><time datetime="2022-09-10T01:00:00.000Z" title="发表于 2022-09-10 09:00:00">2022-09-10</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/posts/16284/" title="每日一面--字符流和字节流">每日一面--字符流和字节流</a><time datetime="2022-07-01T01:00:00.000Z" title="发表于 2022-07-01 09:00:00">2022-07-01</time></div></div></div></div></div></div></main><footer id="footer" style="background-image: url('https://gcore.jsdelivr.net/gh/PaulGeorge123/cloudimg@img/mig2023/background05.jpg')"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2023 By PaulGeorge</div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.min.js"></script><script src="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.js"></script><div class="js-pjax"></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="is-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span>  数据库加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div><hr/><div id="local-search-results"></div></div></div><div id="search-mask"></div><script src="/js/search/local-search.js"></script></div></body></html>